home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / mailbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  59.2 KB  |  2,524 lines

  1. /* There are only two functions in this mailbox code that depend on the
  2.  * underlying protocol, namely mbx_getname() and dotalktosysop(). All the
  3.  * other functions can hopefully be used without modification on other
  4.  * stream oriented protocols than AX.25 or NET/ROM.
  5.  *
  6.  * SM0RGV 890506, most work done previously by W9NK
  7.  *
  8.  *** Changed 900114 by KA9Q to use newline mapping features in stream socket
  9.  *    interface code; everything here uses C eol convention (\n)
  10.  *
  11.  *    Numerous new commands and other changes by SM0RGV, 900120
  12.  *                                             and G1YYH,  901014
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <time.h>
  17. #include <ctype.h>
  18. #ifdef    UNIX
  19. #include <sys/types.h>
  20. #endif
  21. #include "global.h"
  22. #include "config.h"
  23. #include "bm.h"
  24. #include "mailbox.h"
  25. #include "cmdparse.h"
  26. #include "proc.h"
  27. #include "socket.h"
  28. #include "usock.h"
  29. #include "ax25.h"
  30. #include "smtp.h"
  31. #include "dirutil.h"
  32. #include "telnet.h"
  33. #include "ftp.h"
  34. #include "ftpserv.h"
  35. #include "netrom.h"
  36. #include "commands.h"
  37. #include "netuser.h"
  38. #include "files.h"
  39. #include <dos.h>
  40. #include <stdlib.h>
  41. #include <ios1.h>
  42. #include <proto/dos.h>
  43. #include "amiga/amiga.h"
  44.  
  45. /*
  46. #define MBDEBUG
  47. */
  48.  
  49. extern int32 Gateway;
  50. extern char *tmpfiles[NUFBS];
  51. extern char Badmsg[];
  52. extern char Nomail[];
  53. extern int timewind __ARGS((int argc,char *argv[],void *p));
  54. extern int tt1, tt2, tnw;
  55.  
  56. char Mbpasswd[MAXPWDLEN+1] = "";
  57. extern char *Arealist, *Helpdir, *Rewritefile;
  58. struct mbx *Mbox[NUMMBX];
  59. struct tm *stime;
  60. char *Organ = NULLCHAR, *Rname = NULLCHAR, *RHdr = NULLCHAR;
  61. static int MBsysop = 0;        /* used for sysop level */
  62. static int MBtrace = 0;        /* used for trace level */
  63. int Attended = 0;        /* default to unattended mode */
  64. int ThirdParty = 0;        /* no 3rd party mail by default */
  65. int EightBit;
  66. unsigned Maxlet = BM_NLET;
  67. static char Mbbanner[] = "%s\nWelcome %s to the %s TCP/IP Mailbox\n%s\n";
  68. static char Mbwarning[] = " - Third Party Message Handling Disabled -\n";
  69. static char Mbmenu[] = "\"%s\" Msg #%d : ?=Commands, H=Help >%s";
  70.  
  71. #if    !defined(AX25) && !defined(AXLINK)
  72. static char Noservice[] = "Service unavailable.\n";
  73. #endif
  74. char Noperm[] = "Permission denied.\n";
  75.  
  76. extern char *mbxtime __ARGS((char *line));
  77. static char Nosock[] = "Can't create socket\n";
  78. static char Loginbanner[] = "\nKA9Q AmigaNOS (%s:%s)\n\n";
  79. static char Howtoend[] = "Terminate with /EX or /NS or ^Z (^A aborts):\n";
  80.  
  81. static int dosend __ARGS((int argc,char *argv[],void *p));
  82. static int dotalktosysop __ARGS((int argc,char *argv[],void *p));
  83. static int dopaging __ARGS((int argc,char *argv[],void *p));
  84. static int dosid __ARGS((int argc,char *argv[],void *p));
  85. static int dorevfwd __ARGS((int argc,char *argv[],void *p));
  86. static int dombescape __ARGS((int argc,char *argv[],void *p));
  87. static int dodownload __ARGS((int argc,char *argv[],void *p));
  88. static int dombupload __ARGS((int argc,char *argv[],void *p));
  89. static int dowhat __ARGS((int argc,char *argv[],void *p));
  90. static int dosysop __ARGS((int argc,char *argv[],void *p));
  91. static int dostars __ARGS((int argc,char *argv[],void *p));
  92. static int doarea __ARGS((int argc,char *argv[],void *p));
  93. static int dombhelp __ARGS((int argc,char *argv[],void *p));
  94. static int dogateway __ARGS((int argc,char *argv[],void *p));
  95. static int dombtelnet __ARGS((int argc,char *argv[],void *p));
  96. #ifdef CHATNODE
  97. static int dombchatnode __ARGS((int argc,char *argv[],void *p));
  98. #endif
  99. #ifdef    DIGGER
  100. static int dombretr __ARGS((int argc,char *argv[],void *p));
  101. #endif
  102. static int dombfinger __ARGS((int argc,char *argv[],void *p));
  103. #ifdef    NETROM
  104. static int dombnrnodes __ARGS((int argc,char *argv[],void *p));
  105. static int dombnrconnect __ARGS((int argc,char *argv[],void *p));
  106. #endif
  107. static int mbx_getname __ARGS((struct mbx *m));
  108. static int mbxrecvline __ARGS((int s,char *buf,int len,int escape));
  109. static int gw_connect __ARGS((struct mbx *m,int s,char *fsocket,int len));
  110. static void gw_input __ARGS((int s,void *notused,void *p));
  111. static void gw_superv __ARGS((int null,void *proc,void *p));
  112. static int mbx_to __ARGS((int argc,char *argv[],void *p));
  113. static int mbx_data __ARGS((struct mbx *m,struct list *cclist,char *extra));
  114. static int msgidcheck __ARGS((char *string));
  115. static int thirdparty __ARGS((struct mbx *m));
  116. static int uuencode __ARGS((FILE *infile,int s,char *infilename));
  117. static int dombmessage __ARGS((int argc,char *argv[],void *p));
  118. static int dombmovemail __ARGS((int argc,char *argv[],void *p));
  119. static int dombports __ARGS((int argc,char *argv[],void *p));
  120. static int randy __ARGS((int len));
  121. static int dombxaccept __ARGS((int argc,char *argv[],void *p));
  122. static int doattend __ARGS((int argc,char *argv[],void *p));
  123. static int domaxmsg __ARGS((int argc,char *argv[],void *p));
  124. static int dombpasswd __ARGS((int argc,char *argv[],void *p));
  125. static int donothing __ARGS((int argc,char *argv[],void *p));
  126. static int dombprofile __ARGS((int argc,char *argv[],void *p));
  127. static int dombxreject __ARGS((int argc,char *argv[],void *p));
  128. static int dombsysop __ARGS((int argc,char *argv[],void *p));
  129. static int dombtrace __ARGS((int argc,char *argv[],void *p));
  130. static int doorganisation __ARGS((int argc,char *argv[],void *p));
  131. static int dorheader __ARGS((int argc,char *argv[],void *p));
  132. static int dorealname __ARGS((int argc,char *argv[],void *p));
  133. static int dombpasswd __ARGS((int argc,char *argv[],void *p));
  134. extern int doipheard __ARGS((int argc,char *argv[],void *p));
  135. static int doeight __ARGS((int argc, char *argv[], void *p));
  136. extern int dumparp __ARGS((int argc, char *argv[], void *p));
  137.  
  138. /* mbx Reject structure */
  139. struct mr {
  140.     struct mr *prev;
  141.     struct mr *next;
  142.     char addr[AXALEN];
  143. };
  144.  
  145. struct mr *Mr;
  146. #define NULLRQ (struct mr *)0
  147.  
  148. static struct cmds Mbcmds[] = {
  149.     "",        doreadnext,    0, 0, NULLCHAR,
  150.     "area",        doarea,        0, 0, NULLCHAR,
  151.     "bye",        domboxbye,    0, 0, NULLCHAR,
  152. #ifdef CHATNODE
  153.     "chatnode",    dombchatnode,    0, 0, NULLCHAR,
  154. #endif
  155.     "download",    dodownload,    0, 2, "D[U] filename",
  156. #ifdef    AX25
  157.     "dheard",    doaxdest,    0, 0, NULLCHAR,
  158. #endif
  159.     "escape",    dombescape,    0, 0, NULLCHAR,
  160.     "finger",    dombfinger,    0, 0, NULLCHAR,
  161.     "gateway",    dogateway,    0, 3, "(G)ateway interface callsigns",
  162.     "help",        dombhelp,    0, 0, NULLCHAR,
  163.     "info",        dombhelp,    0, 0, NULLCHAR,
  164.     "iparp",    dumparp,        0, 0, NULLCHAR,
  165.     "ipheard",    doipheard,    0, 0, NULLCHAR,
  166.     "iproute",    doroute,    0, 0, NULLCHAR,
  167. #ifdef    AX25
  168.     "jheard",    doaxheard,    0, 0, NULLCHAR,
  169. #endif
  170.     "kill",        dodelmsg,    0, 2, "(K)ill numbers",
  171.     "list",        dolistnotes,    0, 0, NULLCHAR,
  172. #ifdef    AX25
  173.     "lheard",    doaxheard,    0, 0, NULLCHAR,
  174. #endif
  175.     "message",    dombmessage,    0, 2, "message <msg>",
  176.     "movemail",    dombmovemail,    0, 0, NULLCHAR,
  177. #ifdef    NETROM
  178.     "nconnect",    dombnrconnect,    0, 2, "nc callsign | node",
  179.     "nodes",    dombnrnodes,    0, 0, NULLCHAR,
  180. #endif
  181.     "os",        dostatus,    0, 0, NULLCHAR,
  182.     "paging",    dopaging,    0, 0, NULLCHAR,
  183.     "ports",    dombports,    0, 0, NULLCHAR,
  184.     "read",        doreadmsg,    0, 2, "(R)ead numbers",
  185. #ifdef    DIGGER
  186.     "retrieve",    dombretr,    0, 0, NULLCHAR,
  187. #endif
  188.     "send",        dosend,        0, 0, NULLCHAR,
  189.     "talktosysop",    dotalktosysop,    0, 0, NULLCHAR,
  190.     "telnet",    dombtelnet,    0, 2, "(T)elnet hostname",
  191.     "upload",    dombupload,    0, 2, "(U)pload filename",
  192.     "verbose",    doreadmsg,    0, 2, "(V)erbose numbers",
  193.     "what",        dowhat,        0, 0, NULLCHAR,
  194.     "?",        dombhelp,    0, 0, NULLCHAR,
  195.     "[",        dosid,        0, 0, NULLCHAR,
  196. #ifdef    AX25
  197.     "f>",        dorevfwd,    0, 0, NULLCHAR,
  198. #endif
  199.     "@",        dosysop,    0, 0, NULLCHAR,
  200.     "***",        dostars,    0, 0, NULLCHAR,
  201.     NULLCHAR,    NULLFP,        0, 0, "Huh ?",
  202. };
  203.  
  204. /* mbox subcommand table */
  205. static struct cmds Mbtab[] = {
  206.     "accept",    dombxaccept,    0, 0, NULLCHAR,
  207.     "attend",    doattend,    0, 0, NULLCHAR,
  208.     "eightbit",    doeight,    0, 0, NULLCHAR,
  209.     "kick",        dombkick,    0, 0, NULLCHAR,
  210.     "maxmsg",    domaxmsg,    0, 0, NULLCHAR,
  211.     "password",    dombpasswd,    0, 0, NULLCHAR,
  212.     "profile",    dombprofile,    0, 0, NULLCHAR,
  213.     "reject",    dombxreject,    0, 0, NULLCHAR,
  214.     "sysop",    dombsysop,    0, 0, NULLCHAR,
  215.     "thirdparty",    dothirdparty,    0, 0, NULLCHAR,
  216.     "timer",    dombtimer,    0, 0, NULLCHAR,
  217.     "trace",    dombtrace,    0, 0, NULLCHAR,
  218.     NULLCHAR,
  219. };
  220.  
  221. int dombox(argc,argv,p)
  222. int argc;
  223. char *argv[];
  224. void *p;
  225. {
  226.     if(argc == 1)
  227.         return domboxdisplay(argc,argv,p);
  228.     return subcmd(Mbtab,argc,argv,p);
  229. }
  230.  
  231. static int dombsysop(argc,argv,p)
  232. int argc;
  233. char *argv[];
  234. void *p;
  235. {
  236.     return setbool(&MBsysop,"MBOX sysop",argc,argv);
  237. }
  238.  
  239. static int dombtrace(argc,argv,p)
  240. int argc;
  241. char *argv[];
  242. void *p;
  243. {
  244.     return setbool(&MBtrace,"MBOX trace",argc,argv);
  245. }
  246.  
  247. static int doeight(argc,argv,p)
  248. int argc;
  249. char *argv[];
  250. void *p;
  251. {
  252.    return setbool(&EightBit,"Telnet 8-Bit Mode",argc,argv);
  253. }
  254.  
  255. #ifdef    DIGGER
  256. static int dombretr(argc,argv,p)
  257. int argc;
  258. char *argv[];
  259. void *p;
  260. {
  261.     char buf[100], command[100];
  262.     char *archive, *specific;
  263.     struct mbx *m;
  264.     FILE *fp;
  265.  
  266.     m = (struct mbx *) p;
  267.  
  268.     tprintf("Do you want a list of archives ? ");
  269.     mbxrecvline(m->user,m->line,MBXLINE,-1);
  270.     if(strstr("yY",m->line) != NULLCHAR) {
  271.         sprintf(buf,"%s/archives", Digger);
  272.         if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  273.             sendfile(fp,m->user,ASCII_TYPE,0);
  274.             fclose(fp);
  275.         }
  276.     }
  277.  
  278.     tprintf("Enter archive name ? ");
  279.     mbxrecvline(m->user,m->line,MBXLINE,-1);
  280.     archive = strdup(m->line);
  281.  
  282.     tprintf("Do you want an index of '%s' ? ",archive);
  283.     mbxrecvline(m->user,m->line,MBXLINE,-1);
  284.     if(strstr("yY",m->line) != NULLCHAR) {
  285.         sprintf(command, "LHA >%s/index -N l %s/%s",
  286.             Digger, Digger, archive);
  287.             if (!Execute(command, 0, 0)) { return (FILE *)NULL; }
  288.             sprintf(buf,"%s/index", Digger);
  289.         if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  290.             sendfile(fp,m->user,ASCII_TYPE,0);
  291.             fclose(fp);
  292.         }
  293.     }
  294.  
  295.     tprintf("Enter file name ? ");
  296.     mbxrecvline(m->user,m->line,MBXLINE,-1);
  297.     specific = strdup(m->line);
  298.     sprintf(buf,"%s/%s", DiggerC, specific);
  299.     if((fp = fopen(buf,READ_TEXT)) == NULLFILE) {
  300.         sprintf(command,"LHA >nil: -N -n -m x %s/%s %s/ %s",
  301.             Digger, archive, DiggerC, specific);
  302.         if (!Execute(command, 0, 0)) { return (FILE *)NULL; }
  303.     } 
  304.  
  305.     if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  306.         sendfile(fp,m->user,ASCII_TYPE,0);
  307.         fclose(fp);
  308.     } 
  309.  
  310.     return 0;
  311. }
  312. #endif
  313.  
  314. static int dopaging(argc,argv,p)
  315. int argc;
  316. char *argv[];
  317. void *p;
  318. {
  319.     struct mbx *m;
  320.     m = (struct mbx *) p;
  321.  
  322.     if(argc == 1)
  323.         tprintf("Paging after %d lines\n", m->flowpage);
  324.     else
  325.         m->flowpage = atoi(argv[1]);
  326.     return 0;
  327. }
  328.  
  329. /* if unattended mode is set, ax25, telnet and maybe other sessions will
  330.  * be restricted.
  331.  */
  332. static int doattend(argc,argv,p)
  333. int argc;
  334. char *argv[];
  335. void *p;
  336. {
  337.     return setbool(&Attended,"Attended flag",argc,argv);
  338. }
  339.  
  340. static int domaxmsg(argc,argv,p)
  341. int argc;
  342. char *argv[];
  343. void *p;
  344. {
  345.     return setuns(&Maxlet,"Maximum messages per area",argc,argv);
  346. }
  347.  
  348. static int dombfinger(argc,argv,p)
  349. int argc;
  350. char *argv[];
  351. void *p;
  352. {
  353.     struct mbx *m;
  354.     char *host, *user = NULLCHAR, buf[8], *newargv[3];
  355.  
  356.     if(argc > 2){
  357.         tprintf("Usage: Finger user@host  or  Finger @host  or  Finger user.\n");
  358.         return 0;
  359.     }
  360.     host = Hostname;
  361.     if(argc == 2){
  362.         if((host = strchr(argv[1], '@')) != NULLCHAR){
  363.             *host = '\0';
  364.             host++;
  365.         } else
  366.             host = Hostname;
  367.         user = argv[1];
  368.     }
  369.     m = (struct mbx *) p;
  370.     m->startmsg = mallocw(80);
  371.     if(user != NULLCHAR)
  372.         sprintf(m->startmsg,"%s\n",user);
  373.     else
  374.         strcpy(m->startmsg,"\n");
  375.     newargv[0] = "telnet";
  376.     newargv[1] = host;
  377.     sprintf(buf,"%d",IPPORT_FINGER);
  378.     newargv[2] = buf;
  379.     return dombtelnet(3,newargv,p);
  380. }
  381.  
  382. int domboxdisplay(argc,argv,p)
  383. int argc;
  384. char *argv[];
  385. void *p;
  386. {
  387.     int i, j, len;
  388.     struct mbx *m;
  389.     char fsocket[MAXSOCKSIZE];
  390.     static char *states[] = {"LOGIN","CMD","SUBJ","DATA","REVFWD",
  391.             "TRYING","FORWARD","CHATNODE","GATEWAY",
  392.             "READ","UPLOAD","DOWNLOAD","TALKSYSOP",
  393.             "WHAT","SYSOPTRY","SYSOP"};
  394.  
  395.     tprintf("User       State    S#  Where\n");
  396.  
  397.     for (i = 0; i < NUMMBX; i++){
  398.         if((m = Mbox[i]) != NULLMBX){
  399.             len = MAXSOCKSIZE;
  400.             j = getpeername(m->user,fsocket,&len);
  401.             if(tprintf("%-11s%-9s%-4u%s\n",m->name,
  402.                    states[m->state],m->user,
  403.                    j != -1 ? psocket(fsocket): "") == EOF)
  404.                 break;
  405.         }
  406.     }
  407.     return 0;
  408. }
  409.  
  410. struct mbx *newmbx()
  411. {
  412.     int i;
  413.     struct mbx *m;
  414.  
  415.     for(i = 0; i < NUMMBX; i++){
  416.         if(Mbox[i] == NULLMBX){
  417.             m = Mbox[i] = (struct mbx *)callocw(1,sizeof(struct mbx));
  418.             m->mbnum = i;
  419.             return m;
  420.         }
  421.     }
  422.     /* If we get here, there are no free mailbox sessions */
  423.     return NULLMBX;
  424. }
  425.  
  426. /* Incoming mailbox session */
  427. void mbx_incom(s,t,p)
  428. int s;
  429. void *t;
  430. void *p;
  431. {
  432.     struct mbx *m;
  433.     char *buf[3], buf2[77];
  434.     FILE *fp;
  435.  
  436.     sockowner(s,Curproc);    /* We own it now */
  437.     /* Secede from the parent's sockets, and use the network socket that
  438.      * was passed to us for both input and output. The reference
  439.      * count on this socket will still be 1; this allows the domboxbye()
  440.      * command to work by closing that socket with a single call.
  441.      * If we return, the socket will be closed automatically.
  442.      */
  443.     close_s(Curproc->output);
  444.     close_s(Curproc->input);
  445.     Curproc->output = Curproc->input = s;
  446.  
  447.     /* We'll do our own flushing right before we read input */
  448.     setflush(s,-1);
  449.  
  450.     mainlog(s,"open MBOX");
  451.     if((m = newmbx()) == NULLMBX){
  452.         tprintf("Too many mailbox sessions\n");
  453.         return;
  454.     }
  455.     m->user = s;
  456.     m->escape = 24;        /* default escape character is Ctrl-X */
  457.     m->flowpage = MAXLIN;
  458.     /* get the name of the remote station */
  459.     if(mbx_getname(m) == -1)
  460.         close_s(s);
  461.  
  462.     m->state = MBX_CMD;    /* start in command state */
  463.     
  464.     /* Now say hi */
  465.     tprintf(Mbbanner,Mversion,m->name,Hostname,
  466.         (ThirdParty || (m->privs & SYSOP_CMD))
  467.             ? "" : ((p = getenv("MBWARN")) == NULL)
  468.                 ? Mbwarning : p);
  469.  
  470.     sprintf(buf2,"%s/Mbox.SignOn",SignOn);
  471.     if((fp = fopen(buf2,READ_TEXT)) != NULLFILE) {
  472.         sendfile(fp,m->user,ASCII_TYPE,0);
  473.         fclose(fp);
  474.     }
  475.  
  476.     /* Enable our local message area */
  477.     buf[1] = m->name;
  478.     doarea(2,buf,m);
  479.     tprintf(Mbmenu,m->area,m->current,"\n");
  480.     while(mbxrecvline(s,m->line,MBXLINE,-1) != EOF){
  481.         if(MBtrace > 0)
  482.             mainlog(s,"MBOX : %s : %s",m->name,m->line);
  483.         if(mbx_parse(m) == 1)
  484.             tprintf("Bad syntax.\n");
  485.         if(!(m->sid & MBX_SID) && isnewprivmail(m) > 0L)
  486.             tprintf("You have new mail.\n");
  487.         scanmail(m);
  488.         tprintf((m->sid & MBX_SID) ? ">\n" : Mbmenu,m->area,m->current," ");
  489.         m->state = MBX_CMD;
  490.     }
  491.     m->flowpage = MAXLIN;
  492.     exitbbs(m);
  493. }
  494.  
  495. void exitbbs(m)
  496. struct mbx *m;
  497. {
  498.     closenotes(m);
  499.     free(m->to);
  500.     free(m->tofrom);
  501.     free(m->origto);
  502.     free(m->tomsgid);
  503.     free(m->path);
  504.     free((char *)m->mbox);
  505.     Mbox[m->mbnum] = NULLMBX;
  506.     free((char *)m);
  507. }
  508.  
  509. /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
  510.  * They have to be treated specially since cmdparse() wants a space between
  511.  * the actual command and its arguments.
  512.  * "SP FOO" is converted to "s  foo" and the second command letter is saved
  513.  * in m->stype. Longer commands like "SEND" are unaffected, except for
  514.  * commands starting with "[", i.e. the SID, since we don't know what it will
  515.  * look like.
  516.  */
  517. static char twocmds[] = "slrd[";        /* S,L,R,D are two-letter commands */
  518. int mbx_parse(m)
  519. struct mbx *m;
  520. {
  521.     char *cp;
  522.     int i;
  523.     char *newargv[2];
  524.     /* Translate entire buffer to lower case */
  525.     for (cp = m->line; *cp != '\0'; ++cp)
  526.         if(isupper(*cp))
  527.             *cp = tolower(*cp);
  528.     /* Skip any spaces at the begining */
  529.     for(cp = m->line;isspace(*cp);++cp)
  530.         ;
  531.     m->stype = ' ';
  532.     if(*cp != '\0' && *(cp+1) != '\0')
  533.     for(i=0; i<strlen(twocmds); ++i){
  534.         if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
  535.          || *cp == '[')){
  536.             if(islower(*(++cp)))
  537.                 m->stype = toupper(*cp); /* Save the second character */
  538.             else
  539.                 m->stype = *cp;
  540.             *cp = ' ';
  541.             break;
  542.         }
  543.     }
  544.     /* See if the input line consists solely of digits */
  545.     for(cp = m->line;isspace(*cp);++cp)
  546.         ;
  547.     newargv[1] = cp;
  548.     for(;*cp != '\0' && isdigit(*cp);++cp)
  549.         ;
  550.     if(*cp == '\0' && strlen(newargv[1]) > 0) {
  551.         newargv[0] = "read";
  552.         return doreadmsg(2,newargv,(void *)m);
  553.     }
  554.     else
  555.         return cmdparse(Mbcmds,m->line,(void *)m);
  556. }
  557.  
  558. static int mbx_getname(m)
  559. struct mbx *m;
  560. {
  561.     char *cp;
  562.     union sp sp;
  563.     char tmp[MAXSOCKSIZE];
  564.     char buf[MBXLINE];
  565.     int len = MAXSOCKSIZE;
  566.     int anony = 0;
  567.     int count = 0;
  568.  
  569.     m->state = MBX_LOGIN;
  570.     sp.p = tmp;
  571.     sp.sa->sa_family = AF_LOCAL;    /* default to AF_LOCAL */
  572.  
  573.     getpeername(m->user,tmp,&len);
  574.     m->family = sp.sa->sa_family;
  575.     m->path = mallocw(MBXLINE);
  576.     /* This is one of the two parts of the mbox code that depends on the
  577.      * underlying protocol. We have to figure out the name of the
  578.      * calling station. This is only practical when AX.25 or NET/ROM is
  579.      * used. Telnet users have to identify themselves by a login procedure.
  580.      */
  581.     sp.p = tmp;
  582.     switch(sp.sa->sa_family){
  583.     case AF_NETROM:
  584.     case AF_AX25:
  585.         /* NETROM and AX25 socket address structures are "compatible" */
  586.         pax25(m->name,sp.ax->ax25_addr);
  587.         cp = strchr(m->name,'-');
  588.         if(cp != NULLCHAR)            /* get rid of SSID */
  589.             *cp = '\0';
  590.         /* SMTP wants the name to be in lower case */
  591.         cp = m->name;
  592.         while(*cp){
  593.             if(isupper(*cp))
  594.                 *cp = tolower(*cp);
  595.             ++cp;
  596.         }
  597.         anony = 1;
  598.         /* Try to find the privileges of this user from the userfile */
  599.         if((m->privs = userlogin(m->name,buf,&m->path,MBXLINE,&anony)) == -1)
  600.             if((m->privs = userlogin("bbs",buf,&m->path,MBXLINE,&anony)) == -1)
  601.                 if((m->privs = userlogin("anonymous",buf,&m->path,MBXLINE,
  602.                      &anony)) == -1){
  603.                         m->privs = 0;
  604.                         free(m->path);
  605.                         m->path = NULLCHAR;
  606.                 }
  607.         if(m->privs & EXCLUDED_CMD)
  608.             return -1;
  609.         return 0;
  610.     case AF_INET:
  611.         m->state = MBX_LOGIN;
  612.         tprintf(Loginbanner,Hostname,inet_ntoa(Ip_addr));
  613.         for(;;){
  614.             if(count++ == 3)
  615.                 return -1;
  616.             tputs("Callsign: ");
  617.             usflush(m->user);
  618.             if(mbxrecvline(m->user,m->name,sizeof(m->name),-1) == EOF)
  619.                 return -1;
  620.             if(*m->name == '\0')
  621.                 continue;
  622.             tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
  623.             usflush(m->user);
  624.             if(mbxrecvline(m->user,buf,MBXLINE,-1) == EOF)
  625.                 return -1;
  626.             tprintf("%c%c%c\n",IAC,WONT,TN_ECHO);
  627.             tputc('\n');
  628.             usflush(m->user);
  629.             if((m->privs = userlogin(m->name,buf,&m->path,MBXLINE,&anony))
  630.              != -1){
  631.                 if(anony)
  632.                     mainlog(m->user,"MBOX login: %s Password: %s",m->name,buf);
  633.                 else
  634.                     mainlog(m->user,"MBOX login: %s",m->name);
  635.                 if(m->privs & EXCLUDED_CMD)
  636.                     return -1;
  637.                 return 0;
  638.             }
  639.             tprintf("ERROR: Callsign/Password Invalid\n");
  640.             *m->name = '\0';
  641.         }
  642.     }
  643.     return 0;
  644. }
  645.  
  646. /* This works like recvline(), but telnet options are answered and the
  647.  * terminating newline character is not put into the buffer. If the
  648.  * incoming character equals the value of escape, any queued input is
  649.  * flushed and -2 returned.
  650.  */
  651. static int mbxrecvline(s,buf,len,escape)
  652. int s;
  653. char *buf;
  654. int len;
  655. int escape;
  656. {
  657.     int c, cnt = 0, opt;
  658.  
  659.     if(buf == NULLCHAR)
  660.         return 0;
  661.     usflush(Curproc->output);
  662.     while((c = recvchar(s)) != EOF){
  663.         if(c == IAC){        /* Telnet command escape */
  664.             if((c = recvchar(s)) == EOF)
  665.                 break;
  666.             if(c != IAC && (opt = recvchar(s)) != EOF){
  667. #ifdef    foo
  668.                 switch(c){
  669.                 case WILL:
  670.                     printf("%c%c%c",IAC,DONT,opt);
  671.                     break;
  672.                 case WONT:
  673.                     printf("%c%c%c",IAC,DONT,opt);
  674.                     break;
  675.                 case DO:
  676.                     printf("%c%c%c",IAC,WONT,opt);
  677.                     break;
  678.                 case DONT:
  679.                     printf("%c%c%c",IAC,WONT,opt);
  680.                 }
  681. #endif
  682. /* to be fixed             usflush(Curproc->output);*/
  683.                 continue;
  684.             }
  685.             if(c != IAC && opt == EOF)
  686.                 break;
  687.         }
  688.         /* ordinary character */
  689.         if(c == '\n')
  690.             break;
  691.         if(uchar(c) == escape){
  692.             if(socklen(s,0)) /* discard any remaining input */
  693.                 recv_mbuf(s,NULL,0,NULLCHAR,0);
  694.             cnt = -2;
  695.             break;
  696.         }
  697.         *buf++ = c;
  698.         ++cnt;
  699.         if(cnt == len - 1)
  700.             break;
  701.     }
  702.     if(c == EOF && cnt == 0)
  703.         return -1;
  704.     *buf = '\0';
  705.     return cnt;
  706. }
  707.  
  708. int domboxbye(argc,argv,p)
  709. int argc;
  710. char *argv[];
  711. void *p;
  712. {
  713.     struct mbx *m;
  714.     register struct usock *up;
  715.  
  716.     m = (struct mbx *)p;
  717.     /* Now say goodbye */
  718.     if((m->privs & SYSOP_CMD))
  719.         tprintf("Goodbye!\n");
  720.     else
  721.         tprintf("Thank you %s, for calling the %s TCP/IP Mailbox.\n",
  722.             m->name, Hostname);
  723.  
  724.     /* nasty hack! we may have screwed up reference count */
  725.     /* by invoking newproc("smtp_send",....); Fudge it!   */
  726.  
  727.     if((up = itop(m->user)) != NULLUSOCK)
  728.         up->refcnt = 1;
  729.  
  730.     close_s(m->user);
  731.     return 0;
  732. }
  733.  
  734. static int dombhelp(argc,argv,p)
  735. int argc;
  736. char *argv[];
  737. void *p;
  738. {
  739.     register struct cmds *cmdp;
  740.     char buf[255];
  741.     int i;
  742.     FILE *fp;
  743.  
  744.     if(*argv[0] == '?') {
  745.         tprintf("Commands available are:\n");
  746.         memset(buf,' ',sizeof(buf));
  747.         buf[75] = '\n';
  748.         buf[76] = '\0';
  749.         cmdp = Mbcmds;    /* Skip initial NULL */
  750.         cmdp++;        /* Skip initial NULL */
  751.         for(i = 0;cmdp->name != NULLCHAR;cmdp++,i = (i+1)%5) {
  752.             strncpy(&buf[i*15],cmdp->name,strlen(cmdp->name));
  753.             if(i == 4){
  754.                 tprintf(buf);
  755.                 memset(buf,' ',sizeof(buf));
  756.                 buf[75] = '\n';
  757.                 buf[76] = '\0';
  758.             }
  759.         }
  760.         if(i != 0)
  761.             tprintf(buf);
  762.         return 0;
  763.     }
  764.     buf[0] = '\0';
  765.     if(argc > 1)
  766.         for(i=0; Mbcmds[i].name != NULLCHAR; ++i)
  767.             if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
  768.                 sprintf(buf,"%s/Mbox.%s",Helpdir,Mbcmds[i].name);
  769.                 break;
  770.             }
  771.     if(buf[0] == '\0')
  772.         if(*argv[0] == 'i')        /* INFO command */
  773.             sprintf(buf,"%s/Mbox.Info",Helpdir);
  774.         else 
  775.             sprintf(buf,"%s/Mbox.Help",Helpdir);
  776.     if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  777.         sendfile(fp,Curproc->output,ASCII_TYPE,0);
  778.         fclose(fp);
  779.     } 
  780.     return 0;
  781. }
  782.  
  783. static int dotalktosysop(argc,argv,p)
  784. int argc;
  785. char *argv[];
  786. void *p;
  787. {
  788.     char buf[8], *newargv[3];
  789.  
  790.     if(Attended){
  791.         newargv[0] = "telnet";
  792.         newargv[1] = Hostname;
  793.         sprintf(buf,"%d",IPPORT_TTYLINK);
  794.         newargv[2] = buf;
  795.         return dombtelnet(3,newargv,p);
  796.     }
  797.     else {
  798.         tprintf("%s\n",((p = getenv("MBATND")) == NULL) 
  799.             ? "Sorry - The system is Unattended.\007" : p);
  800.     }
  801. }
  802.  
  803. static int dosend(argc,argv,p)
  804. int argc;
  805. char *argv[];
  806. void *p;
  807. {
  808.     register struct mr *lp;
  809.     int cccnt = 0, fail = 0, rcolon = 0, pcolon;
  810.     time_t tb;
  811.     char *host, *cp, fullfrom[MBXLINE],
  812.          sigwork[LINELEN], *rhdr = NULLCHAR;
  813.     struct list *ap, *cclist = NULLLIST;
  814.     struct mbx *m;
  815.     FILE *fp;
  816.  
  817.     m = (struct mbx *)p;
  818.     if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m)
  819.        == -1){
  820.         if(m->sid & MBX_SID)
  821.             tprintf("NO - syntax error\n");
  822.         else {
  823.             tprintf("S command syntax error - format is:\n");
  824.             tprintf("  S[F] name [@ host] [< from_addr] [$bulletin_id]\n");
  825.             tprintf("  SR [number]\n");
  826.         }
  827.         return 0;
  828.     }
  829.     if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
  830.         if(m->sid & MBX_SID)
  831.             tputs("NO - ");
  832.         tprintf("Already have %s\n",m->tomsgid);
  833.         return 0;
  834.     }
  835.  
  836.     for(lp = Mr;lp != NULLRQ;lp = lp->next) 
  837.         if(strncmp(m->to,lp->addr,strlen(lp->addr)) == 0) {
  838.             mainlog(-1,"Mailbox rejected mail to '%s'",m->to);
  839.             printf("\x1b[32mMailbox: Rejected Mail To '\x1b[33m%s\x1b[32m'\x1b[0m\n",m->to);
  840.             tprintf("NO - Unwanted address\n");
  841.             return 0;
  842.         }
  843.  
  844.     if(m->stype == 'R' && !(m->sid & MBX_SID) &&
  845.        mbx_reply(argc,argv,m,&cclist,&rhdr) == -1)
  846.         return 0;
  847.     if((cp = rewrite_address(m->to)) != NULLCHAR)
  848.          if(strcmp(m->to,cp) != 0){
  849.           m->origto = m->to;
  850.           m->to = cp;
  851.          } else
  852.           free(cp);
  853.     if((m->origto != NULLCHAR || m->stype == 'R') && !(m->sid & MBX_SID))
  854.         tprintf("To: %s\n", m->to);
  855.     if(!ThirdParty && !(m->privs & SYSOP_CMD))
  856.         if(thirdparty(m) == 0){
  857.             tprintf("Third party mail not permitted!\n");
  858.             return 0;
  859.         }
  860.     if(validate_address(m->to) == 0){
  861.         if(m->sid & MBX_SID)
  862.             tprintf("NO - bad address\n");
  863.         else
  864.             tprintf("Bad user or host name\n");
  865.         free(rhdr);
  866.         del_list(cclist);
  867.         /* We don't free any more buffers here. They are freed upon
  868.          * the next call to mbx_to() or to domboxbye()
  869.          */
  870.         return 0;
  871.     }
  872.     /* Display the Cc: line (during SR command) */
  873.     for(ap = cclist; ap != NULLLIST; ap = ap->next) {
  874.         if(cccnt == 0){
  875.             tprintf("%s",Hdrs[CC]);
  876.             cccnt = 4;
  877.         }
  878.         else {
  879.             tputs(", ");
  880.             cccnt += 2;
  881.         }
  882.         if(cccnt + strlen(ap->val) > 80 - 3) {
  883.             tputs("\n    ");
  884.             cccnt = 4;
  885.         }
  886.         tputs(ap->val);
  887.         cccnt += strlen(ap->val);
  888.     }
  889.     if(cccnt)
  890.         tputc('\n');
  891.     m->state = MBX_SUBJ;
  892.     if(m->stype != 'R' || (m->sid & MBX_SID) != 0) {
  893.         tprintf((m->sid & MBX_SID) ? "OK\n" : "Subject: ");
  894.         if(mbxrecvline(m->user,m->line,MBXLINE,-1) == -1)
  895.             return 0;
  896.     }
  897.     else                /* Replying to a message */
  898.         tprintf("Subject: %s\n",m->line);
  899.     if(mbx_data(m,cclist,rhdr) == -1){
  900.         free(rhdr);
  901.         del_list(cclist);
  902.         tputs("Can't create temp file for mail\n");
  903.         return 0;
  904.     }
  905.     free(rhdr);
  906.     m->state = MBX_DATA;
  907.     if((m->sid & MBX_SID) == 0 && m->stype != 'F')
  908.         tprintf("Enter message.  %s",Howtoend);
  909.  
  910.     if (RHdr != NULLCHAR) {
  911.         time(&tb);
  912.         fprintf(m->tfile,"R:%s @:%s #:%ld\n", 
  913.                         mbxtime(ptime(&tb)), RHdr,
  914.             get_msgid() - 1);
  915.     }
  916.  
  917.     if(m->stype != 'F' || (m->sid & MBX_SID) != 0)
  918.     {
  919.         while(mbxrecvline(m->user,m->line,MBXLINE,-1) != -1)
  920.         {
  921.             if(m->line[0] == 0x01){  /* CTRL-A */
  922.                 fclose(m->tfile);
  923.                 tputs("Aborted.\n");
  924.                 del_list(cclist);
  925.                 return 0;
  926.             }
  927.             pcolon = rcolon;
  928.             if(m->line[0] != CTLZ &&
  929.                  stricmp(m->line, "/ex") &&
  930.                  stricmp(m->line, "/ns")) {
  931.                 rcolon = (strncmp(m->line,"R:",2) != 0);
  932.                 if(pcolon != rcolon)
  933.                     fprintf(m->tfile,"\n");
  934.                 fprintf(m->tfile,"%s\n",m->line);
  935.             } else
  936.                 break;    /* all done */
  937.         }
  938.     } else {
  939.         fprintf(m->tfile,"----- Forwarded message -----\n\n");
  940.         msgtofile(m,m->current,m->tfile,0);
  941.         fprintf(m->tfile,"----- End of forwarded message -----\n");
  942.     }
  943.  
  944.     if(stricmp(m->line, "/ns"))
  945.        /* Insert customised signature if one is found */
  946.        if(!(m->sid & MBX_SID)) {    /* not a forwarding BBS */
  947.           sprintf(sigwork,"%s/%s.sig",Signature,
  948.                   m->tofrom ? m->tofrom : m->name);
  949.           if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE) {
  950.              while(fgets(sigwork,LINELEN,fp) != NULLCHAR)
  951.                 fputs(sigwork,m->tfile);
  952.                 fclose(fp);
  953.           }
  954.        }
  955.  
  956.     if((host = strrchr(m->to,'@')) == NULLCHAR) {
  957.         host = Hostname;    /* use our hostname */
  958.         if(m->origto != NULLCHAR) {
  959.             /* rewrite_address() will be called again by our
  960.              * SMTP server, so revert to the original address.
  961.              */
  962.              free(m->to);
  963.             m->to = m->origto;
  964.             m->origto = NULLCHAR;
  965.         }
  966.     }
  967.     else
  968.         host++;    /* use the host part of address */
  969.  
  970.     /* make up full from name for work file */
  971.  
  972.     if(m->tofrom)
  973.         sprintf(fullfrom,"%s%%%s.bbs@%s",m->tofrom, m->name, Hostname);
  974.     else
  975.         sprintf(fullfrom,"%s@%s",m->name,Hostname);
  976.  
  977.     if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
  978.         fseek(m->tfile,0L,0);    /* reset to beginning */
  979.         fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
  980.         del_list(cclist);
  981.         cclist = NULLLIST;
  982.     }
  983.     addlist(&cclist,m->to,0);
  984.     fseek(m->tfile,0L,0);
  985.     fail += queuejob(m->tfile,host,cclist,fullfrom);
  986.     del_list(cclist);
  987.     fclose(m->tfile);
  988.     if(fail)
  989.          tputs("Couldn't queue message for delivery\n");
  990.     else
  991.          if(m->tomsgid != NULLCHAR &&
  992.         (fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
  993.           fprintf(fp,"%s\n",m->tomsgid); /* Save BID in history file */
  994.           fclose(fp);
  995.          }
  996.     return 0;
  997. }
  998.  
  999. static int dosid(argc,argv,p)
  1000. int argc;
  1001. char *argv[];
  1002. void *p;
  1003. {
  1004.     struct mbx *m;
  1005.     char *biddy;
  1006.  
  1007.     m = (struct mbx *)p;
  1008.     if(argc == 1)
  1009.         return 1;
  1010.     if(argv[1][strlen(argv[1]) - 1] != ']') /* must be an SID */
  1011.         return 1;
  1012.     m->sid = MBX_SID;
  1013.     /* Now check to see if this is an RLI board.
  1014.      * As usual, Hank does it a bit differently from
  1015.      * the rest of the world.
  1016.      */
  1017.     if(m->stype == 'R' && strncmp(argv[1],"li",2) == 0)/* [RLI] at a minimum */
  1018.         m->sid |= MBX_RLI_SID;
  1019.     /* Check to see if the BBS supports a kludge called "hierarchical
  1020.      * routing designators."
  1021.      */
  1022.     biddy = strchr(strrchr(argv[1],'-'),'h');
  1023.     /* printf("** %s **\n", biddy); */
  1024.     if(strlen(argv[1]) > 2 && (biddy != NULLCHAR))
  1025.         m->sid |= MBX_HIER_SID;
  1026.     return 0;
  1027. }
  1028.  
  1029. static int dombescape(argc,argv,p)
  1030. int argc;
  1031. char *argv[];
  1032. void *p;
  1033. {
  1034.     struct mbx *m;
  1035.  
  1036.     m = (struct mbx *)p;
  1037.     if(argc < 2){
  1038.         tprintf("The escape character is: ");
  1039.         if(m->escape < 32)
  1040.             tprintf("CTRL-%c\n",m->escape+'A'-1);
  1041.         else
  1042.             tprintf("'%c'\n",m->escape);
  1043.         return 0;
  1044.     }
  1045.     if(strlen(argv[1]) > 1)
  1046.         if(isdigit(*argv[1]))
  1047.             m->escape = (char) atoi(argv[1]);
  1048.         else
  1049.             return 1;
  1050.     else
  1051.         m->escape = *argv[1];
  1052.     return 0;
  1053. }
  1054.  
  1055. static int dodownload(argc,argv,p)
  1056. int argc;
  1057. char *argv[];
  1058. void *p;
  1059. {
  1060.     struct mbx *m;
  1061.     FILE *fp;
  1062.     char *file;
  1063.  
  1064.     if(timewind(NULL,NULLCHAR,NULL)) {
  1065.         tprintf("Command Ignored - Access '%2d:00-%2d:59 %s' only\n", tt1, tt2,
  1066.             ((p = getenv("TZ")) == NULL) ? "GMT" : p);
  1067.         return 0;
  1068.     } 
  1069.     m = (struct mbx *)p;
  1070.     file = pathname(m->path,argv[1]);
  1071.     if(!permcheck(m->path,m->privs,RETR_CMD,file)){
  1072.         tprintf(Noperm);
  1073.         return 0;
  1074.     }
  1075.     m->state = MBX_DOWNLOAD;
  1076.     if((fp = fopen(file,READ_TEXT)) == NULLFILE)
  1077.         tprintf("Can't open \"%s\": %s\n",file,sys_errlist[errno]);
  1078.     else
  1079.         if(m->stype == 'U'){            /* uuencode ? */
  1080.             fclose(fp);
  1081.             fp = fopen(file,READ_BINARY);    /* assume non-ascii */
  1082.             uuencode(fp,m->user,file);
  1083.         } else {
  1084.             if(isbinary(fp)) {
  1085.                 tprintf("File:  %s\nAppears to be BINARY so is being sent UUencoded\n\n",file);
  1086.                 fclose(fp);
  1087.                 fp = fopen(file,READ_BINARY);    /* assume non-ascii */
  1088.                 uuencode(fp,m->user,file);
  1089.             } else 
  1090.             sendfile(fp,m->user,ASCII_TYPE,0);
  1091.         }
  1092.     free(file);
  1093.     fclose(fp);
  1094.     return 0;
  1095. }
  1096.  
  1097. static int dombupload(argc,argv,p)
  1098. int argc;
  1099. char *argv[];
  1100. void *p;
  1101. {
  1102.     struct mbx *m;
  1103.     FILE *fp;
  1104.     char *file, buf[LINELEN];
  1105.  
  1106.     m = (struct mbx *)p;
  1107.     file = pathname(m->path,argv[1]);
  1108.     if(!permcheck(m->path,m->privs,STOR_CMD,file)){
  1109.         tprintf(Noperm);
  1110.         return 0;
  1111.     }
  1112.     if((fp = fopen(file,WRITE_TEXT)) == NULLFILE){
  1113.         tprintf("Can't create \"%s\": %s\n",file,sys_errlist[errno]);
  1114.         free(file);
  1115.         return 0;
  1116.     }
  1117.     mainlog(m->user,"MBOX upload: %s",file);
  1118.     m->state = MBX_UPLOAD;
  1119.     tprintf("Send file,  %s",Howtoend);
  1120.     for(;;){
  1121.         if(mbxrecvline(m->user,buf,LINELEN,-1) == -1){
  1122.             unlink(file);
  1123.             break;
  1124.         }
  1125.         if(buf[0] == 0x01){  /* CTRL-A */
  1126.             unlink(file);
  1127.             tprintf("Aborted.\n");
  1128.             break;
  1129.         }
  1130.         if(buf[0] == CTLZ || !stricmp("/ex",buf))
  1131.             break;
  1132.         fprintf(fp,"%s",buf);
  1133. #if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA)
  1134.         /* Needed only if the OS uses a CR/LF
  1135.          * convention and fputc doesn't do
  1136.          * an automatic translation
  1137.          */
  1138.         if(fputc('\r',fp) == EOF)
  1139.             break;
  1140. #endif
  1141.         if(fputc('\n',fp) == EOF)
  1142.             break;
  1143.     }
  1144.     free(file);
  1145.     fclose(fp);
  1146.     return 0;
  1147. }
  1148.  
  1149. static int dowhat(argc,argv,p)
  1150. int argc;
  1151. char *argv[];
  1152. void *p;
  1153. {
  1154.     struct mbx *m;
  1155.     FILE *fp;
  1156.     char *file;
  1157.  
  1158.     m = (struct mbx *)p;
  1159.     if(argc < 2)
  1160.         file = strdup(m->path);
  1161.     else
  1162.         file = pathname(m->path,argv[1]);
  1163.     if(!permcheck(m->path,m->privs,RETR_CMD,file)){
  1164.         tprintf(Noperm);
  1165.         return 0;
  1166.     }
  1167.     if((fp = dir(file,1)) == NULLFILE)
  1168.         tprintf("Can't read directory: \"%s\": %s\n",file,sys_errlist[errno]);
  1169.     else
  1170.         sendfile(fp,m->user,ASCII_TYPE,0);
  1171.     free(file);
  1172.     fclose(fp);
  1173.     return 0;
  1174. }
  1175.  
  1176. static int dosysop(argc,argv,p)
  1177. int argc;
  1178. char *argv[];
  1179. void *p;
  1180. {
  1181.     struct mbx *m;
  1182.     int c, len, pwdc[5], i, valid = 0;
  1183.     char *cp;
  1184.     extern struct cmds Cmds[];
  1185.  
  1186.     m = (struct mbx *) p;
  1187.     mainlog(m->user,"MBOX: %s attempting SYSOP",m->name);
  1188.     if(!(m->privs & SYSOP_CMD)){
  1189.         tprintf(Noperm);
  1190.         return 0;
  1191.     }
  1192.  
  1193.     /* check for the password before letting users proceed */
  1194.     m->state = MBX_SYSOPTRY;
  1195.     if((len = strlen(Mbpasswd)) != 0) {
  1196.         for (i=0; i<5; i++)
  1197.             tprintf("%d ",(pwdc[i] = randy(len)));
  1198.         tputc('\n');
  1199.         while(1) {
  1200.             c = mbxrecvline(m->user, m->line, MBXLINE, -1);
  1201.             if(c == EOF || c == -2)
  1202.                 return 0;
  1203.             if(*m->line == '\0')
  1204.                 break;
  1205.             cp = m->line;
  1206.             for(i=0;i<5;i++)
  1207.                 if(*cp++ != Mbpasswd[pwdc[i]])
  1208.                     break;
  1209.             if (i == 5)
  1210.                 valid = 1;
  1211.         }
  1212.         if(!valid)
  1213.             return 0;
  1214.     }
  1215.  
  1216.     mainlog(m->user,"MBOX: %s has the correct SYSOP password",m->name);
  1217.  
  1218.     if(MBsysop) {
  1219.         mainlog(m->user,"MBOX: %s is now SYSOP",m->name);
  1220.         m->state = MBX_SYSOP;
  1221.         dombescape(1,NULLCHAR,p);
  1222.         for(;;){
  1223.                     long currtime;
  1224.                     time(&currtime);
  1225.                     stime = localtime(&currtime);
  1226.                     tprintf("SYSOP <%02d:%02d - %s> ",stime->tm_hour, stime->tm_min, Hostname);
  1227.             usflush(Curproc->output);
  1228.             c = mbxrecvline(Curproc->input,m->line,MBXLINE,m->escape);
  1229.             if(c == EOF || c == -2)
  1230.                 break;
  1231.             mainlog(m->user,"MBOX sysop: %s",m->line);
  1232.             cmdparse(Cmds,m->line,NULL);
  1233.         }
  1234.         return 0;
  1235.     } else {
  1236.         tprintf("Sorry! - MBOX Sysop turned off\007\n");
  1237.         return 0;
  1238.     }
  1239. }
  1240.  
  1241. /* Handle the "*** Done" command when reverse forwarding ends or the
  1242.  * "*** LINKED to" command.
  1243.  */
  1244. static int dostars(argc,argv,p)
  1245. int argc;
  1246. char *argv[];
  1247. void *p;
  1248. {
  1249.     struct mbx *m;
  1250.     int anony = 1;
  1251.     m = (struct mbx *)p;
  1252.     /* The "*** LINKED to" command is only allowed to stations with
  1253.      * SYSOP privileges to prevent others from obtaining the same.
  1254.      */
  1255.     if((m->privs & SYSOP_CMD) && argc == 4 && !strcmp(argv[1],"linked")) {
  1256.         strcpy(m->name, argv[3]);
  1257.         /* Try to find the privileges of this user from the userfile */
  1258.         if((m->privs = userlogin(m->name,NULLCHAR,&m->path,MBXLINE,
  1259.                      &anony)) == -1)
  1260.              if((m->privs = userlogin("bbs",NULLCHAR,&m->path,
  1261.                       MBXLINE,&anony)) == -1)
  1262.               if((m->privs = userlogin("anonymous",NULLCHAR,
  1263.                        &m->path,MBXLINE,&anony)) == -1){
  1264.                         m->privs = 0;
  1265.                         free(m->path);
  1266.                         m->path = NULLCHAR;
  1267.               }
  1268.         tprintf("Oh, hello %s.\n",m->name);
  1269.         if(m->privs & EXCLUDED_CMD)
  1270.             return domboxbye(0,NULLCHARP,p);
  1271.         changearea(m,m->name);
  1272.         return 0;
  1273.     }
  1274.     if(argc > 1 && (m->sid & MBX_SID))    /* "*** Done" or similar */
  1275.         return 2;
  1276.     return -1;
  1277. }
  1278.  
  1279. static int doarea(argc,argv,p)
  1280. int argc;
  1281. char *argv[];
  1282. void *p;
  1283. {
  1284.     struct mbx *m;
  1285.     char buf[MBXLINE], *cp;
  1286.     char *cp2, *area;
  1287.     FILE *fp;
  1288.  
  1289.     m = (struct mbx *) p;
  1290.     if(argc < 2){
  1291.         tprintf("Current message area is: %s\n",m->area);
  1292.         tprintf("Available areas are:\n%-15s  Your private mail area\n",
  1293.           m->name);
  1294.         if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
  1295.             return 0;
  1296.         sendfile(fp,m->user,ASCII_TYPE,0);
  1297.         fclose(fp);
  1298.         return 0;
  1299.     }
  1300.     if((m->privs & SYSOP_CMD) || strcmp(m->name,argv[1]) == 0){
  1301.         /*Private mail-areas*/
  1302.         changearea(m,argv[1]);
  1303.         if(m->nmsgs){
  1304.             if(!strcmp(m->name,m->area))
  1305.                 tprintf("You have ");
  1306.             else {
  1307.                 area = strdup(m->area);
  1308.                 while((cp2 = strchr(area,'/')) != NULLCHAR)
  1309.                     *cp2 = '.';
  1310.                 tprintf("%s: ",area);
  1311.             }
  1312.             tprintf("%d message%s -  %d new.\n", m->nmsgs,
  1313.               m->nmsgs == 1 ? " " : "s ", m->newmsgs);
  1314.         }
  1315.         return 0;
  1316.     }
  1317.     if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE){
  1318.         tprintf("There are no public message areas.\n");
  1319.         return 0;
  1320.     }
  1321.     while(fgets(buf,MBXLINE,fp) != NULLCHAR){
  1322.         /* The first word on each line is all that matters */
  1323.         if((cp = strchr(buf,' ')) == NULLCHAR)
  1324.             if((cp = strchr(buf,'\t')) == NULLCHAR)
  1325.                 continue;
  1326.         *cp = '\0';
  1327.         if((cp = strchr(buf,'\t')) != NULLCHAR)
  1328.             *cp = '\0';
  1329.         if(stricmp(argv[1],buf) == 0){
  1330.             changearea(m,argv[1]);
  1331.             area = strdup(m->area);
  1332.             while((cp2 = strchr(area,'/')) != NULLCHAR)
  1333.                 *cp2 = '.';
  1334.             tprintf("%s: %d message%s.\n", area, m->nmsgs,
  1335.               m->nmsgs == 1 ? "" : "s");
  1336.             fclose(fp);
  1337.             return 0;
  1338.         }
  1339.     }
  1340.     fclose(fp);
  1341.     tprintf("No such message area as: %s\n",argv[1]);
  1342.     return 0;
  1343. }
  1344.  
  1345. /* subroutine to do the actual switch from one area to another */
  1346. void changearea(m,area)
  1347. struct mbx *m;
  1348. char *area;
  1349. {
  1350.     char *cp;
  1351.  
  1352.     closenotes(m);
  1353.     m->nmsgs = m->newmsgs = m->current = 0;
  1354.     strcpy(m->area, area);
  1355.     while((cp = strchr(m->area,'.')) != NULLCHAR)
  1356.         *cp = '/';
  1357.     scanmail(m);
  1358. }
  1359.  
  1360. #ifdef AX25
  1361. static int dogateway(argc,argv,p)
  1362. int argc;
  1363. char *argv[];
  1364. void *p;
  1365. {
  1366.     struct mbx *m;
  1367.     struct sockaddr_ax fsocket;
  1368.     int ndigis,i,s;
  1369.     char digis[MAXDIGIS][AXALEN];
  1370.     char target[AXALEN];
  1371.  
  1372.     m = (struct mbx *)p;
  1373.     if(!(m->privs & AX25_CMD)){
  1374.         tprintf(Noperm);
  1375.         return 0;
  1376.     }
  1377.     /* If digipeaters are given, put them in the routing table */
  1378.     if(argc > 3){
  1379.         setcall(target,argv[2]);
  1380.         ndigis = argc - 3;
  1381.         if(ndigis > MAXDIGIS){
  1382.             tprintf("Too many digipeaters\n");
  1383.             return 1;
  1384.         }
  1385.         for(i=0;i<ndigis;i++){
  1386.             if(setcall(digis[i],argv[i+3]) == -1){
  1387.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  1388.                 return 1;
  1389.             }
  1390.         }
  1391.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  1392.             tprintf("Route add failed\n");
  1393.             return 1;
  1394.         }
  1395.     }
  1396.     if((s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  1397.         tprintf(Nosock);
  1398.         return 0;
  1399.     }
  1400.     fsocket.sax_family = AF_AX25;
  1401.     setcall(fsocket.ax25_addr,argv[2]);
  1402.     strncpy(fsocket.iface,argv[1],ILEN);
  1403.     m->startmsg = mallocw(80);
  1404.     sprintf(m->startmsg,"*** LINKED to %s\n",m->name);
  1405.     return gw_connect(m,s,(char *)&fsocket, sizeof(struct sockaddr_ax));
  1406. }
  1407. #else
  1408. static int dogateway(argc,argv,p)
  1409. int argc;
  1410. char *argv[];
  1411. void *p;
  1412. {
  1413.     tputs(Noservice);
  1414.     return 0;
  1415. }
  1416. #endif
  1417.  
  1418. static int dombtelnet(argc,argv,p)
  1419. int argc;
  1420. char *argv[];
  1421. void *p;
  1422. {
  1423.     struct mbx *m;
  1424.     int s, len, i;
  1425.     char dsocket[MAXSOCKSIZE];
  1426.     struct sockaddr_in fsocket;
  1427.  
  1428.     m = (struct mbx *) p;
  1429.     fsocket.sin_family = AF_INET;
  1430.     if(argc < 3)
  1431.         fsocket.sin_port = IPPORT_TELNET;
  1432.     else
  1433.         fsocket.sin_port = atoi(argv[2]);
  1434.  
  1435.     if((fsocket.sin_addr.s_addr = resolve(argv[1])) == 0){
  1436.         tprintf(Badhost,argv[1]);
  1437.         return 0;
  1438.     }
  1439.     /* Only local telnets are are allowed to the unprivileged user */
  1440.     if(!(m->privs & TELNET_CMD) && !ismyaddr(fsocket.sin_addr.s_addr)){
  1441.         tprintf(Noperm);
  1442.         return 0;
  1443.     }
  1444.     if((s = socket(AF_INET,SOCK_STREAM,0)) == -1){
  1445.         tprintf(Nosock);
  1446.         return 0;
  1447.     }
  1448.     switch(fsocket.sin_port) {
  1449.     case IPPORT_TTYLINK:
  1450.         m->startmsg = callocw(1,80);
  1451.         len = MAXSOCKSIZE;
  1452.         i = getpeername(m->user,dsocket,&len);
  1453.         sprintf(m->startmsg,"*** Incoming call from %s@%s ***\n",
  1454.             m->name,(i != -1) ? psocket(dsocket): Hostname);
  1455.         break;
  1456. #ifdef CHATNODE
  1457.     case IPPORT_CHATNODE:
  1458.         if(m->startmsg == NULLCHAR) {
  1459.             m->startmsg = callocw(1,40);
  1460.             sprintf(m->startmsg,
  1461.                 "/n %s %d\n",m->name,(argc > 3) ? atoi(argv[3]) : 0);
  1462.         }
  1463.         m->state = MBX_CHATNODE;
  1464.         break;
  1465. #endif
  1466.     }
  1467.     m->state = MBX_GATEWAY;
  1468.     return gw_connect(m,s,(char *)&fsocket,SOCKSIZE);
  1469. }
  1470.  
  1471. /* Generic mbox gateway code. It sends and frees the contents of m->startmsg
  1472.  * when the connection has been established unless it a null pointer.
  1473.  */
  1474. static int gw_connect(m,s,fsocket,len)
  1475. struct mbx *m;
  1476. int s;
  1477. char *fsocket;
  1478. int len;
  1479. {
  1480.     int c;
  1481.     char *cp;
  1482.     struct proc *child;
  1483.  
  1484.     child = newproc("gateway supervisor",256,gw_superv,0,Curproc,m);
  1485.     tprintf("Trying %s...  ",psocket((struct sockaddr *)fsocket));
  1486.     dombescape(0,NULLCHARP,(void *)m);
  1487.     usflush(Curproc->output);
  1488.     if(connect(s,fsocket,len) == -1){
  1489.         cp = sockerr(s);
  1490.         tprintf("Connection failed: ");
  1491.         if(cp != NULLCHAR)
  1492.             tprintf("%s errno %d\n",cp,errno);
  1493.         else
  1494.             tprintf("Escape character sent.\n");
  1495.         free(m->startmsg);
  1496.         m->startmsg = NULLCHAR;
  1497.         killproc(child);
  1498.         close_s(s);
  1499.         return 0;
  1500.     }
  1501.     /* The user did not type the escape character */
  1502.     killproc(child);
  1503.     tputs("Connected.\n");
  1504.     
  1505.     if(m->startmsg != NULLCHAR){
  1506.         usputs(s,m->startmsg);
  1507.         free(m->startmsg);
  1508.         m->startmsg = NULLCHAR;
  1509.     }
  1510.     /* Fork off the receive process */
  1511.     child = newproc("gateway in",1024,gw_input,s,NULL,Curproc);
  1512.     
  1513.     for(;;){
  1514.         alarm(240/MSPTICK);    /* Arrange for automatic flushing */
  1515.         c = recvchar(Curproc->input);
  1516.         if(c == EOF) {
  1517.             if(sockerr(s) != NULLCHAR) /* something is wrong */
  1518.                 break;
  1519.             if(errno == EALARM){
  1520.                 usflush(s);
  1521.                 continue;
  1522.             } else
  1523.                 break;
  1524.         }
  1525.         if(c == m->escape){
  1526.             tputs("Disconnecting.");
  1527.             if(socklen(Curproc->input,0))
  1528.                 recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
  1529.             break;
  1530.         }
  1531.         if(usputc(s,(char)c) == EOF)
  1532.             break;
  1533.     }
  1534.     alarm(0);
  1535.     close_s(s);
  1536.     killproc(child); /* get rid of the receive process */
  1537.     tprintf("%c%c%c\n",IAC,WONT,TN_ECHO);
  1538.     return 0;
  1539. }
  1540.  
  1541. static void gw_input(s,notused,p)
  1542. int s;
  1543. void *notused;
  1544. void *p;
  1545. {
  1546.     int c;
  1547.     char *cp;
  1548.     struct proc *parent;
  1549.  
  1550.     parent = (struct proc *) p;
  1551.     for(;;){
  1552.         /* Since NOS does not flush the output socket after a certain
  1553.          * period of time, we have to arrange that ourselves. */
  1554.         alarm(240/MSPTICK);
  1555.         c = recvchar(s);
  1556.         if(c == EOF)
  1557.             if(errno == EALARM){
  1558.                 usflush(Curproc->output);
  1559.                 continue;
  1560.             } else
  1561.                 break;
  1562.         tputc((char)c);
  1563.     }
  1564.     alarm(0);
  1565.     tprintf("Disconnected ");
  1566.     cp = sockerr(s);
  1567.     if(cp != NULLCHAR)
  1568.         tputs(cp);
  1569.     /* Tell the parent that we are no longer connected */
  1570.     alert(parent,ENOTCONN);
  1571.     pwait(Curproc); /* Now wait to be killed */
  1572. }
  1573.  
  1574. /* Check if the escape character is typed while the parent process is busy
  1575.  * doing other things. 
  1576.  */
  1577. static void gw_superv(null,proc,p)
  1578. int null;
  1579. void *proc;
  1580. void *p;
  1581. {
  1582.     struct proc *parent;
  1583.     struct mbx *m;
  1584.     int c;
  1585.     parent = (struct proc *) proc;
  1586.     m = (struct mbx *) p;
  1587.     while((c = recvchar(Curproc->input)) != EOF)
  1588.         if(c == m->escape){
  1589.             /* flush anything in the input queue */
  1590.             if(socklen(Curproc->input,0))
  1591.                 recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
  1592.             break;
  1593.         }
  1594.     alert(parent,EINTR);     /* Tell the parent to quit */
  1595.     pwait(Curproc);         /* Please kill me */
  1596. }
  1597.  
  1598. #ifdef    NETROM
  1599.  
  1600. /* Called every time a blank line is received. */
  1601. static int donothing(argc,argv,p)
  1602. int argc;
  1603. char *argv[];
  1604. void *p;
  1605. {
  1606.     return 0;
  1607. }
  1608.  
  1609. static int dombnrnodes(argc,argv,p)
  1610. int argc;
  1611. char *argv[];
  1612. void *p;
  1613. {
  1614.     if(Nrifaces[0].iface == NULLIF){
  1615.         tprintf("NET/ROM not activated.\n");
  1616.         return 0;
  1617.     }
  1618.     if(argc < 2)
  1619.         return doroutedump();
  1620.     return dorouteinfo(argc,argv,p);
  1621. }
  1622.  
  1623. static int dombnrconnect(argc,argv,p)
  1624. int argc;
  1625. char *argv[];
  1626. void *p;
  1627. {
  1628.     struct mbx *m;
  1629.     char *np, buf[7];
  1630.     int s;
  1631.     struct sockaddr_nr lsocket, fsocket;
  1632.     char alias[AXBUF];
  1633.  
  1634.     if(Nrifaces[0].iface == NULLIF){
  1635.         tprintf("NET/ROM not activated.\n");
  1636.         return 0;
  1637.     }
  1638.     m = (struct mbx *) p;
  1639.     if(!(m->privs & NETROM_CMD)){
  1640.         tprintf(Noperm);
  1641.         return 0;
  1642.     }
  1643.     if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  1644.         tprintf(Nosock);
  1645.         return 0;
  1646.     }
  1647.     lsocket.nr_family = AF_NETROM;
  1648.     /* Set up our local username, bind would use Mycall instead */
  1649.     if(strlen(m->name) > 6)
  1650.         strncpy(buf, m->name,6);
  1651.     else
  1652.         strcpy(buf, m->name);
  1653.     buf[6] = '\0';
  1654.     putalias(alias,buf,0);
  1655.     setcall(lsocket.nr_addr.user,alias);
  1656.  
  1657.     /* Putting anything else than Mycall here will not work */
  1658.     memcpy(lsocket.nr_addr.node,Mycall,AXALEN);
  1659.     bind(s,(char *)&lsocket,sizeof(struct sockaddr_nr));
  1660.  
  1661.     /* See if the requested destination could be an alias, and
  1662.      * find and use it if it is.  Otherwise assume it is an ax.25
  1663.      * address.
  1664.      */
  1665.     if(putalias(alias,argv[1],0) != -1 &&
  1666.         (np = find_nralias(alias)) != NULLCHAR){
  1667.         memcpy(fsocket.nr_addr.user,np,AXALEN);
  1668.         memcpy(fsocket.nr_addr.node,np,AXALEN);
  1669.     } else {    /* parse ax25 callsign */
  1670.         /* Only the user callsign of the remote station is never used by */
  1671.         /* NET/ROM, but it is needed for the psocket() call. */
  1672.         setcall(fsocket.nr_addr.user,argv[1]);
  1673.         setcall(fsocket.nr_addr.node,argv[1]);
  1674.     }
  1675.     fsocket.nr_family = AF_NETROM;
  1676.     return gw_connect(m,s,(char *)&fsocket, sizeof(struct sockaddr_nr));
  1677. }
  1678. #endif
  1679.  
  1680. /* States for send line parser state machine */
  1681. #define        LOOK_FOR_USER        2
  1682. #define        IN_USER            3
  1683. #define        AFTER_USER        4
  1684. #define        LOOK_FOR_HOST        5
  1685. #define        IN_HOST            6
  1686. #define        AFTER_HOST        7
  1687. #define        LOOK_FOR_FROM        8
  1688. #define        IN_FROM            9
  1689. #define        AFTER_FROM        10
  1690. #define        LOOK_FOR_MSGID        11
  1691. #define        IN_MSGID        12
  1692. #define        FINAL_STATE        13
  1693. #define        ERROR_STATE        14
  1694.  
  1695. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  1696.  * return 0
  1697.  */
  1698. static int mbx_to(argc,argv,p)
  1699. int argc;
  1700. char *argv[];
  1701. void *p;
  1702. {
  1703.     register char *cp;
  1704.     int state, i;
  1705.     char *user, *host, *from, *msgid;
  1706.     int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0;
  1707.     struct mbx *m;
  1708.     
  1709.     m = (struct mbx *)p;
  1710.     /* Free anything that might be allocated
  1711.      * since the last call to mbx_to()
  1712.      */
  1713.     free(m->to);
  1714.     m->to = NULLCHAR;
  1715.     free(m->tofrom);
  1716.     m->tofrom = NULLCHAR;
  1717.     free(m->tomsgid);
  1718.     m->tomsgid = NULLCHAR;
  1719.     free(m->origto);
  1720.     m->origto = NULLCHAR;
  1721.  
  1722.     if(argc == 1)
  1723.         return -1;
  1724.     i = 1;
  1725.     cp = argv[i];
  1726.     state = LOOK_FOR_USER;
  1727.     while(state < FINAL_STATE){
  1728. #ifdef MBDEBUG
  1729.         tprintf("State is %d, char is %c\n", state, *cp);
  1730. #endif
  1731.         switch(state){
  1732.         case LOOK_FOR_USER:
  1733.             if(*cp == '@' || *cp == '<' || *cp == '$'){
  1734.                 state = ERROR_STATE;        /* no user */
  1735.             } else {
  1736.                 user = cp;            /* point at start */
  1737.                 userlen++;            /* start counting */
  1738.                 state = IN_USER;
  1739.             }
  1740.             break;
  1741.         case IN_USER:
  1742.             switch(*cp){
  1743.             case '\0':
  1744.                 state = AFTER_USER;        /* done with username */
  1745.                 break;
  1746.             case '@':
  1747.                 state = LOOK_FOR_HOST;        /* hostname should follow */
  1748.                 break;
  1749.             case '<':
  1750.                 state = LOOK_FOR_FROM;        /* from name should follow */
  1751.                 break;
  1752.             case '$':
  1753.                 state = LOOK_FOR_MSGID;    /* message id should follow */
  1754.                 break;
  1755.             default:
  1756.                 userlen++;            /* part of username */
  1757.             }
  1758.             break;
  1759.         case AFTER_USER:
  1760.             switch(*cp){
  1761.             case '@':
  1762.                 state = LOOK_FOR_HOST;        /* hostname follows */
  1763.                 break;
  1764.             case '<':
  1765.                 state = LOOK_FOR_FROM;        /* fromname follows */
  1766.                 break;
  1767.             case '$':
  1768.             state = LOOK_FOR_MSGID;    /* message id follows */
  1769.                 break;
  1770.             default:
  1771.                 state = ERROR_STATE;
  1772.             }
  1773.             break;
  1774.         case LOOK_FOR_HOST:
  1775.             if(*cp == '@' || *cp == '<' || *cp == '$'){
  1776.                 state = ERROR_STATE;
  1777.                 break;
  1778.             }
  1779.             if(*cp == '\0')
  1780.                 break;
  1781.             host = cp;
  1782.             hostlen++;
  1783.             state = IN_HOST;
  1784.             break;
  1785.         case IN_HOST:
  1786.             switch(*cp){
  1787.             case '\0':
  1788.                 state = AFTER_HOST;        /* found user@host */
  1789.                 break;
  1790.             case '@':
  1791.                 state = ERROR_STATE;        /* user@host@? */
  1792.                 break;
  1793.             case '<':
  1794.                 state = LOOK_FOR_FROM;        /* fromname follows */
  1795.                 break;
  1796.             case '$':
  1797.                 state = LOOK_FOR_MSGID;    /* message id follows */
  1798.                 break;
  1799.             default:
  1800.                 hostlen++;
  1801.             }
  1802.             break;
  1803.         case AFTER_HOST:
  1804.             switch(*cp){
  1805.             case '@':
  1806.                 state = ERROR_STATE;        /* user@host @ */
  1807.                 break;
  1808.             case '<':
  1809.                 state = LOOK_FOR_FROM;        /* user@host < */
  1810.                 break;
  1811.             case '$':
  1812.                 state = LOOK_FOR_MSGID;    /* user@host $ */
  1813.                 break;
  1814.             default:
  1815.                 state = ERROR_STATE;        /* user@host foo */
  1816.             }
  1817.             break;
  1818.         case LOOK_FOR_FROM:
  1819.             if(*cp == '@' || *cp == '<' || *cp == '$'){
  1820.                 state = ERROR_STATE;
  1821.                 break;
  1822.             }
  1823.             if(*cp == '\0')
  1824.                 break;
  1825.             from = cp;
  1826.             fromlen++;
  1827.             state = IN_FROM;
  1828.             break;
  1829.         case IN_FROM:
  1830.             switch(*cp){
  1831.             case '\0':
  1832.                 state = AFTER_FROM;        /* user@host <foo */
  1833.                 break;
  1834.             case '<':
  1835.                 state = ERROR_STATE;        /* user@host <foo< */
  1836.                 break;
  1837.             case '$':
  1838.                 state = LOOK_FOR_MSGID;    /* message id follows */
  1839.                 break;
  1840.             default:
  1841.                 fromlen++;
  1842.             }
  1843.             break;
  1844.         case AFTER_FROM:
  1845.             switch(*cp){
  1846.             case '@':                /* user@host <foo @ */
  1847.             case '<':                /* user@host <foo < */
  1848.                 state = ERROR_STATE;
  1849.                 break;
  1850.             case '$':
  1851.                 state = LOOK_FOR_MSGID;    /* user@host <foo $ */
  1852.                 break;
  1853.             default:
  1854.                 state = ERROR_STATE;        /* user@host foo */
  1855.             }
  1856.             break;
  1857.         case LOOK_FOR_MSGID:
  1858.             if(*cp == '\0')
  1859.                 break;
  1860.             msgid = cp;
  1861.             msgidlen++;
  1862.             state = IN_MSGID;
  1863.             break;
  1864.         case IN_MSGID:
  1865.             if(*cp == '\0')
  1866.                 state = FINAL_STATE;
  1867.             else
  1868.                 msgidlen++;
  1869.             break;
  1870.         default:
  1871.             /* what are we doing in this state? */
  1872.             state = ERROR_STATE;
  1873.         }
  1874.         if(*(cp) == '\0'){
  1875.             ++i;
  1876.             if(i < argc)
  1877.             cp = argv[i];
  1878.             else break;
  1879.         } else
  1880.             ++cp;
  1881.     }
  1882.     if(state == ERROR_STATE || state == LOOK_FOR_HOST
  1883.      || state == LOOK_FOR_FROM || state == LOOK_FOR_MSGID)
  1884.         return -1;        /* syntax error */
  1885.  
  1886.     m->to = mallocw(userlen + hostlen + 2);
  1887.  
  1888.     strncpy(m->to, user, userlen);
  1889.     m->to[userlen] = '\0';
  1890.     
  1891.     if(hostlen){
  1892.         m->to[userlen] = '@';
  1893.         strncpy(m->to + userlen + 1, host, hostlen);
  1894.         m->to[userlen + hostlen + 1] = '\0';
  1895.     }
  1896.     if(fromlen){
  1897.         m->tofrom = mallocw(fromlen + 1);
  1898.         strncpy(m->tofrom, from, fromlen);
  1899.         m->tofrom[fromlen] = '\0';
  1900.     }
  1901.     if(msgidlen){
  1902.         m->tomsgid = mallocw(msgidlen + 1);
  1903.         strncpy(m->tomsgid, msgid, msgidlen);
  1904.         m->tomsgid[msgidlen] = '\0';
  1905.     }
  1906.     return 0;
  1907. }
  1908.  
  1909. /* This opens the data file and writes the mail header into it.
  1910.  * Returns 0 if OK, and -1 if not.
  1911.  */
  1912. static int mbx_data(m,cclist,extra)
  1913. struct mbx *m;
  1914. struct list *cclist;    /* list of carbon copy recipients */
  1915. char *extra;        /* optional extra header lines */
  1916. {
  1917.     time_t t;
  1918.     int32 id;
  1919.     struct list *ap;
  1920.     int cccnt = 0;
  1921.     char buf[20], *cp;
  1922.  
  1923.     if((m->tfile = tmpfile()) == NULLFILE)
  1924.         return -1;
  1925.  
  1926.     pax25(buf,Mycall);
  1927.     if((cp=strchr(buf,'-')) != NULLCHAR)
  1928.         *cp = '\0';
  1929.     for (cp = buf; *cp != '\0'; ++cp)
  1930.         if(isupper(*cp)) 
  1931.             *cp = tolower(*cp);
  1932.     
  1933.     time(&t);
  1934.     id = get_msgid();
  1935.  
  1936. #ifdef AX25
  1937.     if(m->family == AF_NETROM || m->family == AF_AX25) {
  1938.         fprintf(m->tfile,"%sfrom %s ", Hdrs[RECEIVED], m->name);
  1939.         fprintf(m->tfile,"by %s with AX25%s\n\tid AA%ld ; %s",
  1940.             Hostname, (m->sid & MBX_SID) ? "FWD" : "",
  1941.             id, ptime(&t));
  1942.     }
  1943. #endif
  1944.     fprintf(m->tfile,"%s%s",Hdrs[DATE],ptime(&t));
  1945.     fprintf(m->tfile,Hdrs[MSGID]);
  1946.     if(m->tomsgid)
  1947.         fprintf(m->tfile,"<%s@%s.bbs>\n", m->tomsgid, m->name); 
  1948.     else
  1949.         fprintf(m->tfile,"<%ld@%s>\n", id, Hostname);
  1950.     fprintf(m->tfile,Hdrs[FROM]);
  1951.     if(m->tofrom)
  1952.         fprintf(m->tfile,"%s%%%s.bbs@%s\n",
  1953.             m->tofrom, m->name, Hostname);
  1954.     else {
  1955.         fprintf(m->tfile,"%s@%s", m->name, Hostname);
  1956.         if ((Rname != NULLCHAR) && !strcmp(m->name,buf))
  1957.             fprintf(m->tfile," (%s)\n", Rname);
  1958.         else 
  1959.             fprintf(m->tfile,"\n");
  1960.     }
  1961.     if ((Organ != NULLCHAR) && !strcmp(m->name,buf))
  1962.         fprintf(m->tfile,"%s%s\n",Hdrs[ORGANISATION],Organ);
  1963.     fprintf(m->tfile,"%s%s\n",Hdrs[TO],
  1964.         m->origto != NULLCHAR ? m->origto : m->to);
  1965.     /* Write Cc: line */
  1966.     for(ap = cclist; ap != NULLLIST; ap = ap->next) {
  1967.         if(cccnt == 0){
  1968.             fprintf(m->tfile,"%s",Hdrs[CC]);
  1969.             cccnt = 4;
  1970.         }
  1971.         else {
  1972.                fprintf(m->tfile,", ");
  1973.                cccnt += 2;
  1974.         }
  1975.         if(cccnt + strlen(ap->val) > 80 - 3) {
  1976.                fprintf(m->tfile,"\n    ");
  1977.                cccnt = 4;
  1978.         }
  1979.         fputs(ap->val,m->tfile);
  1980.         cccnt += strlen(ap->val);
  1981.     }
  1982.     if(cccnt)
  1983.         fputc('\n',m->tfile);
  1984.     fprintf(m->tfile,"%s%s\n",Hdrs[SUBJECT],m->line);
  1985.     if (!strcmp(m->name,buf))
  1986.         fprintf(m->tfile,"%sAmigaNOS v%s\n",Hdrs[COMMENT],Version);
  1987.     if(!isspace(m->stype) && ((m->stype != 'R' && m->stype != 'F') ||
  1988.       (m->sid & MBX_SID) !=0))
  1989.           fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],m->stype);
  1990.     if(extra != NULLCHAR)
  1991.         fprintf(m->tfile,extra);
  1992.     fprintf(m->tfile,"\n");
  1993.  
  1994.     return 0;
  1995. }
  1996.  
  1997. /* Returns true if string is in history file or if string
  1998.    appears to be a message id generated by our system. */
  1999. static int msgidcheck(string)
  2000. char *string;
  2001. {
  2002.      FILE *fp;
  2003.      char buf[LINELEN], *cp;
  2004.      if(string == NULLCHAR)
  2005.       return 0;
  2006.      /* BID's that we have generated ourselves are not kept in the history
  2007.       * file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
  2008.       * our hostname, truncated so that the BID is no longer than 11
  2009.       * characters.
  2010.       */
  2011.      if((cp = strchr(string,'_')) != NULLCHAR && *(cp+1) != '\0' && 
  2012.     strnicmp(cp+1,Hostname,strlen(cp+1)) == 0)
  2013.       return 1;
  2014.  
  2015.      if((fp = fopen(Historyfile,READ_TEXT)) == NULLFILE)
  2016.       return 0;
  2017.      while(fgets(buf,LINELEN,fp) != NULLCHAR) {
  2018.       rip(buf);
  2019.       if(stricmp(string,buf) == 0) {    /* found */
  2020.            fclose(fp);
  2021.            return 1;
  2022.       }
  2023.      }
  2024.      fclose(fp);
  2025.      return 0;
  2026. }
  2027.      
  2028. #ifndef    AXLINK
  2029. int doaxheard(argc,argv,p)
  2030. int argc;
  2031. char *argv[];
  2032. void *p;
  2033. {
  2034.     tputs(Noservice);
  2035.     return 0;
  2036. }
  2037. #endif
  2038.  
  2039. /* Read the rewrite file for lines where the first word is a regular
  2040.  * expression and the second word are rewriting rules. The special
  2041.  * character '$' followed by a digit denotes the string that matched
  2042.  * a '*' character. The '*' characters are numbered from 1 to 9.
  2043.  * Example: the line "*@*.* $2@$1.ampr.org" would rewrite the address
  2044.  * "foo@bar.xxx" to "bar@foo.ampr.org".
  2045.  * $H is replaced by our hostname, and $$ is an escaped $ character.
  2046.  * If the third word on the line has an 'r' character in it, the function
  2047.  * will recurse with the new address.
  2048.  */
  2049. char *rewrite_address(addr)
  2050. char *addr;
  2051. {
  2052.     char *argv[10], buf[MBXLINE], *cp, *cp2, *retstr;
  2053.     int cnt;
  2054.     FILE *fp;
  2055.     if ((fp = fopen(Rewritefile,READ_TEXT)) == NULLFILE)
  2056.         return NULLCHAR;
  2057.     memset((char *)argv,0,10*sizeof(char *));
  2058.     while(fgets(buf,MBXLINE,fp) != NULLCHAR) {
  2059.         if(*buf == '#')        /* skip commented lines */
  2060.             continue;
  2061.         if((cp = strchr(buf,' ')) == NULLCHAR) /* get the first word */
  2062.             if((cp = strchr(buf,'\t')) == NULLCHAR)
  2063.                 continue;
  2064.         *cp = '\0';
  2065.         if((cp2 = strchr(buf,'\t')) != NULLCHAR){
  2066.             *cp = ' ';
  2067.             cp = cp2;
  2068.             *cp = '\0';
  2069.         }
  2070.         if(!wildmat(addr,buf,argv))
  2071.             continue;        /* no match */
  2072.         rip(++cp);
  2073.         cp2 = retstr = (char *) callocw(1,MBXLINE);
  2074.         while(*cp != '\0' && *cp != ' ' && *cp != '\t')
  2075.             if(*cp == '$') {
  2076.                 if(isdigit(*(++cp)))
  2077.                     if(argv[*cp - '0'-1] != '\0')
  2078.                         strcat(cp2,argv[*cp - '0'-1]);
  2079.                 if(*cp == 'h' || *cp == 'H') /* Our hostname */
  2080.                     strcat(cp2,Hostname);
  2081.                 if(*cp == '$')    /* Escaped $ character */
  2082.                     strcat(cp2,"$");
  2083.                 cp2 = retstr + strlen(retstr);
  2084.                 cp++;
  2085.             }
  2086.             else
  2087.                 *cp2++ = *cp++;
  2088.         for(cnt=0; argv[cnt] != NULLCHAR; ++cnt)
  2089.             free(argv[cnt]);
  2090.         fclose(fp);
  2091.         /* If there remains an 'r' character on the line, repeat
  2092.          * everything by recursing.
  2093.          */
  2094.         if(strchr(cp,'r') != NULLCHAR || strchr(cp,'R') != NULLCHAR) {
  2095.             if((cp2 = rewrite_address(retstr)) != NULLCHAR) {
  2096.                 free(retstr);
  2097.                 return cp2;
  2098.             }
  2099.         }
  2100.         return retstr;
  2101.     }
  2102.     fclose(fp);
  2103.     return NULLCHAR;
  2104. }
  2105.  
  2106. /* uuencode a file -- translated from C++; both versions copyright 1990
  2107.    by David R. Evans, G4AMJ/NQ0I
  2108. */
  2109. static int uuencode(infile,s,infilename)
  2110. FILE *infile;
  2111. int s;            /* output socket */
  2112. char *infilename;
  2113. {
  2114.     int n_read_so_far = 0, n_written_so_far = 0, in_chars, n,
  2115.     mode = 0755;
  2116.     unsigned int cnt = 0;
  2117.     unsigned char in[3], out[4], line[100];
  2118.     char *cp;
  2119.  
  2120.     if((cp = strrchr(infilename,'/')) != NULLCHAR)
  2121.         *cp++;
  2122.  
  2123.     usprintf(s, "begin %03o %s\n", mode, (cp != NULLCHAR) ? cp : infilename);
  2124.  
  2125. /*    usprintf(s, "begin %03o %s\n", mode, infilename); */
  2126.  
  2127.     /* do the encode */
  2128.     while ((in_chars = fread(in, 1, 3, infile)) != 0) {
  2129.         out[0] = in[0] >> 2;
  2130.         out[1] = in[0] << 6;
  2131.         out[1] = out[1] >> 2;
  2132.         out[1] = out[1] | (in[1] >> 4);
  2133.         out[2] = in[1] << 4;
  2134.         out[2] = out[2] >> 2;
  2135.         out[2] = out[2] | (in[2] >> 6);
  2136.         out[3] = in[2] << 2;
  2137.         out[3] = out[3] >> 2;
  2138.         for (n = 0; n < 4; n++)
  2139.             out[n] += ' ';
  2140.         n_read_so_far += in_chars;
  2141.         for (n = 0; n < 4; n++)
  2142.             line[n_written_so_far++] = out[n];
  2143.         if ((in_chars != 3) || (n_written_so_far == 60)) {
  2144.             line[(n_read_so_far + 2) / 3 * 4] = '\0';
  2145.             usprintf(s,"%c%s\n",n_read_so_far + ' ', line);
  2146.             cnt += n_read_so_far;
  2147.             n_read_so_far = 0;
  2148.             n_written_so_far = 0;
  2149.         }
  2150.     }
  2151.     if (usprintf(s," \nend\nsize %u\n", cnt) == EOF)
  2152.         return 1;
  2153.     return 0;
  2154. }
  2155.  
  2156. /* if ThirdParty is not set - restrict the mailbox (S)end command to local only */
  2157. dothirdparty(argc,argv,p)
  2158. int argc;
  2159. char *argv[];
  2160. void *p;
  2161. {
  2162.     return setbool(&ThirdParty,"Third-Party mail flag",argc,argv);
  2163. }
  2164.  
  2165. /* Attempt to determine if this is third-party mail. */
  2166. static int thirdparty(m)
  2167. struct mbx *m;
  2168. {
  2169.     char buf[MBXLINE], *cp, *rp;
  2170.     FILE *fp;
  2171.  
  2172.     if(strchr(m->to,'@') != NULLCHAR || strchr(m->to,'%') != NULLCHAR
  2173.             || strchr(m->to,'!') != NULLCHAR)
  2174.         return 0;
  2175.  
  2176.     rp = strdup(Hostname);
  2177.  
  2178.     if((cp = strchr(rp, '.')) != NULLCHAR)
  2179.         *cp = '\0';
  2180.  
  2181.     if(stricmp(m->to,rp) == 0){
  2182.         free(rp);
  2183.         return -1;
  2184.     }
  2185.     free(rp);
  2186.  
  2187.     if(stricmp(m->to,"sysop") == 0)
  2188.         return -1;
  2189.     if(stricmp(m->to,"digger") == 0)
  2190.         return -1;
  2191.  
  2192.     if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
  2193.         return 0;
  2194.  
  2195.     while(fgets(buf,MBXLINE,fp) != NULLCHAR){
  2196.         /* The first word on each line is all that matters */
  2197.         if((cp = strchr(buf, ' ')) != NULLCHAR)
  2198.             *cp = '\0';
  2199.         if((cp = strchr(buf,'\t')) != NULLCHAR)
  2200.             *cp = '\0';
  2201.         if(stricmp(m->to,buf) == 0){
  2202.             fclose(fp);
  2203.             return -1;
  2204.         }
  2205.     }
  2206.     fclose(fp);
  2207.     return 0;
  2208. }
  2209.  
  2210. static int dombmessage(argc,argv,p)
  2211. int argc;
  2212. char *argv[];
  2213. void *p;
  2214. {
  2215.     struct mbx *m;
  2216.     char msg[256];
  2217.     int i;
  2218.  
  2219.     m = (struct mbx *) p;
  2220.     msg[0] = '\0';
  2221.  
  2222.     /* collect rest of args as message */
  2223.     for (i=1;i<argc;i++) {
  2224.         strcat(msg,argv[i]);
  2225.         strcat(msg," ");
  2226.     }
  2227.  
  2228.     printf("\a\n\x1b[32m*** Message from \x1b[33m%s\x1b[0m:\n\x1b[32m'\x1b[33m%s\x1b[32m'\x1b[0m\n",m->name,msg);
  2229.  
  2230.     return 0;
  2231. }
  2232.  
  2233. #ifdef CHATNODE
  2234. static int dombchatnode(argc,argv,p)
  2235. int argc;
  2236. char *argv[];
  2237. void *p;
  2238. {
  2239.     struct mbx *m;
  2240.     char buf[8], *newargv[3];
  2241.  
  2242.     m = (struct mbx *) p;
  2243.  
  2244.     m->startmsg = callocw(1,40);
  2245.     sprintf(m->startmsg,"/n %s %s\n",m->name,(argc > 1) ? argv[1] : "0");
  2246.     newargv[0] = "telnet";
  2247.     newargv[1] = Hostname;
  2248.     sprintf(buf,"%d",IPPORT_CHATNODE);
  2249.     newargv[2] = buf;
  2250.     return dombtelnet(3,newargv,p);
  2251. }
  2252. #endif
  2253.  
  2254. /* Move messages from current area to another */
  2255. int dombmovemail(argc,argv,p)
  2256. int argc;
  2257. char *argv[];
  2258. void *p;
  2259. {
  2260.     int num,i;
  2261.     int move[NARG];
  2262.     char *to;
  2263.     struct mbx *m;
  2264.     char buf[MBXLINE];
  2265.     FILE * Mfile;           /* file to move to */
  2266.     struct let *cmsg;
  2267.     long size;
  2268.     int thisone;
  2269.  
  2270.     m = (struct mbx *)p;
  2271.  
  2272.     if(!(m->privs & SYSOP_CMD)) {
  2273.         tprintf("%s\n",Noperm);
  2274.         return 0;
  2275.     }
  2276.  
  2277.     if(argc == 1) {
  2278.         tputs("Syntax: movemail area - moves current message\n"
  2279.               "        movemail n1 [n2...] area - move message n1 (n2...)\n");
  2280.         return 0;
  2281.     }
  2282.     if(m->mfile == NULLFILE) {
  2283.         tputs(Nomail);
  2284.         return 0;
  2285.     }
  2286.     if(argc == 2) {
  2287.         /* NO message #, use current message */
  2288.         num = 1;
  2289.         to = argv[1];
  2290.         move[0] = m->current;
  2291.     } else {
  2292.         /* Scan all message # to move */
  2293.         num=0;
  2294.         for(i=1;i<argc-1;i++) {
  2295.             if( (move[num]=atoi(argv[i])) != 0 )
  2296.                 if(move[num] <= m->nmsgs)
  2297.                     num++;
  2298.             else
  2299.                 tprintf(Badmsg, argv[i]);
  2300.         }
  2301.         to = argv[argc-1];
  2302.     }
  2303. #ifdef notdef
  2304.     /* translate '.' and '\' to '/' */
  2305.     for(cp=to;*cp!='\0';cp++)
  2306.         if((*cp == '.') || (*cp == '\'))
  2307.             *cp = '/';
  2308. #endif
  2309.  
  2310.     /* Now try to lock the destination file */
  2311.     if(mlock(Mailspool,to) == -1) {
  2312.         tprintf("Can't lock '%s', please try later\n",to);
  2313.         return 0;
  2314.     }
  2315.     /* open the destination file for appending */
  2316.     sprintf(buf,"%s/%s.txt",Mailspool,to);
  2317.     if((Mfile=fopen(buf,"a")) == NULLFILE) {
  2318.         tprintf("Can't open '%s'\n",buf);
  2319.         rmlock(Mailspool,to);
  2320.         return 0;
  2321.     }
  2322.     /* Okay, let's do the work */
  2323.     for(i=0;i<num;i++) {
  2324.         thisone = move[i];
  2325.         cmsg = &m->mbox[thisone];
  2326.         /* find start of this message */
  2327.         fseek(m->mfile,cmsg->start,0);
  2328.         size = cmsg->size;
  2329.         /* now read this message */
  2330.         while(size > 0 && fgets(buf,MBXLINE,m->mfile)!= NULLCHAR) {
  2331.             fputs(buf,Mfile);
  2332.             size -= strlen(buf);
  2333.         }
  2334.         /* delete this message */
  2335.         cmsg->status |= BM_DELETE;
  2336.         m->change = 1;
  2337.         tprintf("Message %d moved...\n",thisone);
  2338.     }
  2339.     fclose(Mfile);
  2340.     rmlock(Mailspool,to);
  2341.     return 0;
  2342. }
  2343.  
  2344. static int dombports(argc,argv,p)
  2345. int argc;
  2346. char *argv[];
  2347. void *p;
  2348. {
  2349.     struct iface *ifp;
  2350.  
  2351.     tputs("Available ports:\n");
  2352.     for(ifp=Ifaces;ifp!=NULLIF;ifp=ifp->next)
  2353.         if(ifp->type == TYPE_AX25) {
  2354.             tprintf("%-7s",ifp->name);
  2355.             if(ifp->descr != NULLCHAR)
  2356.                 tprintf(":  %s",ifp->descr);
  2357.             else
  2358.                 tputc('\n');
  2359.         }
  2360.     tputc('\n');
  2361.     return 0;
  2362. }
  2363.  
  2364. static int dombpasswd(argc,argv,p)
  2365. int argc;
  2366. char *argv[];
  2367. void *p;
  2368. {
  2369.     int len;
  2370.  
  2371.     if(argc != 2) {
  2372.         tputs("Usage: mbox password \"<sysop password>\"\n");
  2373.         return 0;
  2374.     }
  2375.     if((len=strlen(argv[1])) == 0)
  2376.         return 0;       /* zero length, don't reset */
  2377.  
  2378.     if(len > MAXPWDLEN) {
  2379.         tputs("Too long\n");
  2380.         return 0;
  2381.     }
  2382.     strcpy(Mbpasswd,argv[1]);
  2383.     return 0;
  2384. }
  2385.  
  2386. unsigned long int next = 1;
  2387.  
  2388. static int randy(len)
  2389. int len;
  2390. {
  2391.     next = next * 1103515245 + 12345;
  2392.     return (int)(next % len);
  2393. }
  2394.  
  2395. static int dombxreject(argc,argv,p)
  2396. int argc;
  2397. char *argv[];
  2398. void *p;
  2399. {
  2400.     register struct mr *lp;
  2401.  
  2402.     if (argc < 2) {
  2403.         tprintf("Unwanted Mail Addresses: ");
  2404.         if(Mr != NULLRQ)
  2405.             for(lp = Mr;lp != NULLRQ;lp = lp->next)
  2406.                 tprintf(" %s",lp->addr);
  2407.         else
  2408.             tprintf(" Empty");
  2409.         tprintf("\n");
  2410.     } else {
  2411.         lp = (struct mr *)callocw(1,sizeof(struct mr));
  2412.         memcpy(lp->addr,argv[1],AXALEN);
  2413.         lp->next = Mr;
  2414.         if(lp->next != NULLRQ)
  2415.             lp->next->prev = lp;
  2416.         Mr = lp;
  2417.         tprintf("'%s' added to unwanted list\n",argv[1]);
  2418.     }
  2419.     return 0;
  2420. }
  2421.  
  2422. static int dombxaccept(argc,argv,p)
  2423. int argc;
  2424. char *argv[];
  2425. void *p;
  2426. {
  2427.     register struct mr *lp;
  2428.  
  2429.     if (argc < 2) 
  2430.         tprintf("string missing!\n");
  2431.     else {
  2432.         for(lp = Mr;lp != NULLRQ;lp = lp->next)
  2433.             if(strstr(argv[1],lp->addr))
  2434.                 break;
  2435.  
  2436.         if(lp == NULLRQ) {
  2437.             tprintf("Not found\n");
  2438.             return 1;
  2439.         }
  2440.  
  2441.         if(lp->prev != NULLRQ)
  2442.             lp->prev->next = lp->next;
  2443.         else
  2444.             Mr = lp->next;
  2445.         if(lp->next != NULLRQ)
  2446.             lp->next->prev = lp->prev;
  2447.  
  2448.         tprintf("'%s' removed from unwanted list\n",argv[1]);
  2449.     }
  2450.     return 0;
  2451. }
  2452.  
  2453. /* -------------------------- Profile Subcommands -------------------- */
  2454.  
  2455. struct cmds MProf[] = {
  2456.    "organisation", doorganisation,  0, 0, NULLCHAR,
  2457.    "realname",     dorealname,      0, 0, NULLCHAR,
  2458.    "rheader",      dorheader,       0, 0, NULLCHAR,
  2459.    NULLCHAR,
  2460. };
  2461.  
  2462. static int dombprofile(argc,argv,p)
  2463. int argc;
  2464. char *argv[];
  2465. void *p;
  2466. {
  2467.    if(argc == 1) {
  2468.  
  2469.       if (Rname != NULLCHAR)
  2470.          tprintf("SYSOP Name   : %s\n",Rname);
  2471.       if (Organ != NULLCHAR)
  2472.          tprintf("Organisation : %s\n",Organ);
  2473.       if (RHdr != NULLCHAR)
  2474.          tprintf("NTS header   : %s\n",RHdr);
  2475.  
  2476.       return 0;
  2477.    }
  2478.    return subcmd(MProf,argc,argv,p);
  2479.  
  2480. }
  2481.  
  2482. static int doorganisation(argc,argv,p)
  2483. int argc;
  2484. char *argv[];
  2485. void *p;
  2486. {
  2487.    if(argc < 2)
  2488.       tprintf("%s\n",Organ);
  2489.    else {
  2490.       free(Organ);
  2491.       Organ = strdup(argv[1]);
  2492.    }
  2493.    return 0;
  2494. }
  2495.  
  2496. static int dorealname(argc,argv,p)
  2497. int argc;
  2498. char *argv[];
  2499. void *p;
  2500. {
  2501.    if(argc < 2)
  2502.       tprintf("%s\n",Rname);
  2503.    else {
  2504.       free(Rname);
  2505.       Rname = strdup(argv[1]);
  2506.    }
  2507.    return 0;
  2508. }
  2509.  
  2510. static int dorheader(argc,argv,p)
  2511. int argc;
  2512. char *argv[];
  2513. void *p;
  2514. {
  2515.    if(argc < 2)
  2516.       tprintf("%s\n",RHdr);
  2517.    else {
  2518.       free(RHdr);
  2519.       RHdr = strdup(argv[1]);
  2520.    }
  2521.    return 0;
  2522. }
  2523.  
  2524.